/* Html.java

	Purpose:

	Description:

	History:
		Mon Jul 25 11:39:49     2005, Created by tomyeh

Copyright (C) 2005 Potix Corporation. All Rights Reserved.

{{IS_RIGHT
	This program is distributed under LGPL Version 2.1 in the hope that
	it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/
package org.zkoss.zul;

import java.io.Writer;

import org.zkoss.json.JavaScriptValue;
import org.zkoss.lang.Objects;
import org.zkoss.zk.ui.sys.HtmlPageRenders;
import org.zkoss.zul.impl.XulElement;

/**
 * A component used to embed the browser native content (i.e., HTML tags)
 * into the output sent to the browser.
 * The browser native content is specified by {@link #setContent}.
 *
 * <p>Notice that {@link Html} generates HTML SPAN to enclose
 * the embedded HTML tags. Thus, you can specify the style
 * ({@link #getStyle}), tooltip {@link #getTooltip} and so on.
 *
 * <pre><code>&lt;html style="border: 1px solid blue"&gt;&lt;![CDATA[
 * &lt;ul&gt;
 *  &lt;li&gt;It is in a SPAN tag.&lt;/li&gt;
 * &lt;/ul&gt;
 * ]]&gt;&lt;/html&gt;</code></pre>
 *
 * <p>The generated HTML tags will look like:
 * <pre><code>&lt;SPAN id="xxx" style="border: 1px solid blue"&gt;
 * &lt;ul&gt;
 *  &lt;li&gt;It is in a SPAN tag.&lt;/li&gt;
 * &lt;/ul&gt;
 * &lt;/SPAN&gt;</code></pre>
 *
 * <p>Since SPAN is used to enclosed the embedded HTML tags, so
 * the following is incorrect.
 *
 * <pre><code>&lt;html&gt;&lt;![CDATA[
 * &lt;table&gt;
 *  &lt;tr&gt;
 *   &lt;td&gt; &lt;-- Incomplete since it is inside SPAN --&gt;
 * ]]&gt;&lt;/html&gt;
 *
 * &lt;textbox/&gt;
 *
 * &lt;html&gt;&lt;![CDATA[
 *   &lt;/td&gt;
 *  &lt;/tr&gt;
 * &lt;/table&gt;
 * ]]&gt;&lt;/html&gt;</code></pre>
 *
 * <p>If you need to generate the HTML tags directly
 * without enclosing with SPAN, you can use the Native namespace,
 * http://www.zkoss.org/2005/zk/native.
 * Refer to <a href="http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/UI_Patterns/HTML_Tags">ZK Developer's Reference</a> for more information.
 *
 * <p>A non-XUL extension.
 *
 * @author tomyeh
 */
public class Html extends XulElement {
    private String _content = "";

    /**
     * Constructs a {@link Html} component to embed HTML tags.
     */
    public Html() {
    }

    /**
     * Constructs a {@link Html} component to embed HTML tags
     * with the specified content.
     */
    public Html(String content) {
        _content = content != null ? content : "";
    }

    /**
     * Returns the embedded content (i.e., HTML tags).
     */
    public String getContent() {
        return _content;
    }

    /**
     * Sets the embedded content (i.e., HTML tags).
     * <p>Default: empty ("").
     * <p>Deriving class can override it to return whatever it wants
     * other than null.
     *
     * <h3>Security Note</h3>
     * <p>Unlike other methods, the content assigned to this method
     * is generated directly to the browser without escaping.
     * Thus, it is better not to have something input by the user to avoid
     * any <a href="http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/Security_Tips/Cross-site_scripting">XSS</a>
     * attach.
     */
    public void setContent(String content) {
        if (content == null)
            content = "";
        if (!Objects.equals(_content, content)) {
            _content = content;
            smartUpdate("content", getContent(), true);
            //allow deriving to override getContent()
        }
    }

    //super//
    protected void renderProperties(org.zkoss.zk.ui.sys.ContentRenderer renderer) throws java.io.IOException {
        super.renderProperties(renderer);

        String cnt = getContent();
        //allow deriving to override getContent()
        if (cnt.length() > 0) {
            final HtmlPageRenders.RenderContext rc = HtmlPageRenders.getRenderContext(null);
            if (rc != null) {
                final Writer cwout = rc.temp;
                cwout.write("<div id=\"");
                cwout.write(getUuid());
                cwout.write("\" style=\"display:none\">");
                cwout.write(cnt);
                cwout.write("</div>\n");
                if (!rc.included) //Use detachChildren() only if not included (since the included page is rendered a bit late because of Include handles _childjs in bind_)
                    cnt = null; //means already generated
            }
            if (cnt == null)
                renderer.render("content", new JavaScriptValue("zk('" + getUuid() + "').detachChildren()"));
            else
                render(renderer, "content", cnt);
        }
    }

    /**
     * Default: not childable.
     */
    protected boolean isChildable() {
        return false;
    }
}
